package com.wsfPro.services.system;

import com.wsfPro.controllers.dto.system.userDetails.UserDetailsImpl;
import com.wsfPro.core.base.SysConstants;
import com.wsfPro.core.base.SystemSession;
import com.wsfPro.core.system.SysUserService;
import com.wsfPro.entities.middle.SysRoleUserEntity;
import com.wsfPro.entities.middle.SysRoleUserEntityPK;
import com.wsfPro.entities.system.SysRoleEntity;
import com.wsfPro.entities.system.SysUserEntity;
import com.wsfPro.repository.redis.RedisRepository;
import com.wsfPro.repository.system.SysUserRepository;
import com.wsfPro.services.base.BaseCodeServiceImpl;
import com.wsfPro.util.EntityUtil;
import com.wsfPro.util.MD5Util;
import com.wsfPro.util.StringUtils;
import com.wsfPro.util.controllerUtil.JsonConstans;
import com.wsfPro.util.controllerUtil.JsonResult;
import com.wsfPro.util.jwt.JwtUtil;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service(value = "sysUserServiceImpl")
public class SysUserServiceImpl extends BaseCodeServiceImpl<SysUserEntity>
    implements SysUserService, UserDetailsService {

  @Autowired private RedisRepository redisRepository;

  @Autowired private JwtUtil jwtUtil;

  @Autowired private SysUserRepository sysUserRepository;

  @Transactional(readOnly = true)
  @Override
  public Map<String, Object> findUserList(Map paramsMap) {
    String cnName = StringUtils.getMapKeyValue(paramsMap, "cnName");
    String pageNoStr = StringUtils.getMapKeyValue(paramsMap, "pageNo");
    String pageSizeStr = StringUtils.getMapKeyValue(paramsMap, "pageSize");
    String sql =
        "SELECT u.id,u.age,u.birthday,u.cnName,u.`code`,u.createTime,\n"
            + "	u.createId,cuser.cnName createName,u.deptId,d.cnName AS departmentName,u.orgId,org.cnName AS orgName,\n"
            + "	u.email,u.enName,u.identityCard,u.isUse,u.loginIp,u.loginTime,u.mobile,u.phone,u.photo,u.remarks,u.version\n"
            + " FROM sys_user u\n"
            + " LEFT JOIN sys_organization org ON org.id = u.orgId\n"
            + " LEFT JOIN sys_department d ON d.id = u.deptId\n"
            + " LEFT JOIN sys_user cuser ON cuser.id = u.createId\n"
            + " WHERE u.code <> 'admin' AND u.isDelete <> 1";
    String orgId = SystemSession.getOrgId();
    if (StringUtils.isBlank(orgId)) {
      return null;
    }
    boolean isHasWhere = false;
    if (!SysConstants.ROOT_ID.getValue().equals(orgId)) {
      sql += " AND u.orgId ='" + orgId + "'";
      isHasWhere = true;
    }
    Map<String, Object> conditionParams = new HashMap<>(3);
    if (StringUtils.isNotBlank(cnName)) {
      if (isHasWhere) {
        sql += " AND u.cnName =:cnName ";
      }
      conditionParams.put("cnName", cnName);
    }
    Integer pageNo = null;
    Integer pageSize = null;
    if (StringUtils.isNotBlank(pageNoStr)) {
      pageNo = Integer.valueOf(pageNoStr);
    }
    if (StringUtils.isNotBlank(pageSizeStr)) {
      pageSize = Integer.valueOf(pageSizeStr);
    }
    return sysUserRepository.findPageByNativeQueryFileds(
        sql, conditionParams, Transformers.ALIAS_TO_ENTITY_MAP, pageNo, pageSize);
  }

  @Override
  public JsonResult doSaveOrUpdate(Map paramsMap) {
    try {
      String id = StringUtils.getMapKeyValue(paramsMap, "id");
      String code = StringUtils.getMapKeyValue(paramsMap, "code");
      boolean isExistCode = isExistCode(code, id);
      if (isExistCode) {
        return JsonResult.putFail(JsonConstans.ERR_CODE_EXISTS);
      }
      SysUserEntity sysUserEntity = null;
      if (StringUtils.isNotBlank(id)) {
        if (paramsMap.containsKey(SysConstants.PASSWORD)) {
          paramsMap.remove(SysConstants.PASSWORD);
        }
        sysUserEntity = sysUserRepository.findById(SysUserEntity.class, id);
        if (sysUserEntity == null) {
          return JsonResult.putFail(JsonConstans.ERR_NOT_EXISTED);
        }
        EntityUtil.putMapDataIntoEntity(paramsMap, sysUserEntity);
        sysUserRepository.update(sysUserEntity);
      } else {
        sysUserEntity = new SysUserEntity();
        EntityUtil.putMapDataIntoEntity(paramsMap, sysUserEntity);
        sysUserEntity.setPassword(MD5Util.encodeMD5(sysUserEntity.getPassword()));
        sysUserEntity.setIsDelete(Boolean.FALSE);
        sysUserRepository.save(sysUserEntity);
      }
      return JsonResult.putSuccess();
    } catch (Exception e) {
      e.printStackTrace();
      return JsonResult.putFail(JsonConstans.OPERATION_FAILURE);
    }
  }

  //  @Transactional(readOnly = true)
  //  @Override
  //  public SysUserEntity getUserMapByCode(String code) {
  //    String sql = "SELECT u.* FROM sys_user u WHERE u.code =:code AND u.isDelete =0";
  //    Map<String, Object> conditionParams = new HashMap<>(1);
  //    conditionParams.put("code", code);
  //    List<SysUserEntity> userList =
  //            sysUserRepository.findByNativeQuery(sql, conditionParams);
  ////            sysUserRepository.findByNativeQuery(sql, conditionParams,
  // Transformers.aliasToBean(SysUserEntity.class));
  //
  //    if (userList.size() > 1) {
  //      throw new RuntimeException("login user has " + (userList.size()));
  //    }
  //    if (userList.size() != 0) {
  //      return userList.get(0);
  //    }
  //    return null;
  //  }

  //  @Override
  //  public JsonResult doLogin(Map paramsMap) {
  //    String usercode = StringUtils.getMapKeyValue(paramsMap, "usercode");
  //    String password = StringUtils.getMapKeyValue(paramsMap, "password");
  //    if (StringUtils.isBlank(usercode) || StringUtils.isBlank(password)) {
  //      return JsonResult.putFail(JsonConstans.ERR_WRONG_PARAM);
  //    } else {
  //      SysUserEntity user = this.getUserMapByCode(usercode);
  //      if (user != null) {
  //        String userPassword = user.getPassword();
  //        password = MD5Util.encodeMD5(password);
  //        if (userPassword.equals(password)) {
  //          SysUserEntity sysUserEntity =
  //                  this.findById(SysUserEntity.class, user.getId().toString());
  ////          sysUserEntity.setUserToken(TokenConstants.generateToken());
  //          this.update(sysUserEntity);
  ////          redisRepository.delSession(user.get.toString());
  ////          userMap.put("userToken", sysUserEntity.getUserToken());
  //          userMap.remove("password");
  //          redisRepository.setSession(userMap);
  //          return JsonResult.putSuccess(userMap);
  //        } else {
  //          return JsonResult.putFail(JsonConstans.ERR_USER_PASSORD_NOTEQUAL);
  //        }
  //      } else {
  //        return JsonResult.putFail(JsonConstans.ERR_USER_PASSORD_NOTEQUAL);
  //      }
  //    }
  //  }

  @Override
  public boolean layout(HttpServletRequest request) {
    boolean isLayout = false;
    String userAccessToken = request.getHeader(SysConstants.USER_ACCESS_TOKEN.getValue());
    if (StringUtils.isNotBlank(userAccessToken)) {
      isLayout = redisRepository.delSession(userAccessToken);
    }
    return isLayout;
  }

  @Override
  public JsonResult addUserRole(Map paramsMap) {

    String roleIds = StringUtils.getMapKeyValue(paramsMap, "roleIds");
    String userId = StringUtils.getMapKeyValue(paramsMap, "userId");
    if (StringUtils.isBlank(userId) || StringUtils.isBlank(roleIds)) {
      return JsonResult.putFail(JsonConstans.ERR_WRONG_PARAM);
    }
    for (String roleId : roleIds.split(",")) {
      SysRoleUserEntityPK sysRoleUserEntityPK = new SysRoleUserEntityPK();
      sysRoleUserEntityPK.setRoleId(roleId);
      sysRoleUserEntityPK.setUserId(userId);
      SysRoleUserEntity sysRoleUserEntity =
          sysUserRepository.findByIdClass(new SysRoleUserEntity(), sysRoleUserEntityPK);
      if (sysRoleUserEntity == null) {
        sysRoleUserEntity = new SysRoleUserEntity();
        sysRoleUserEntity.setRoleId(roleId);
        sysRoleUserEntity.setUserId(userId);
        sysRoleUserEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
        sysUserRepository.save(sysRoleUserEntity);
      }
    }
    //    sysRoleUserRepository.deleteByRoleUserId(userId, roleIds);
    return JsonResult.putSuccess();
  }

  @Transactional(readOnly = true)
  @Override
  public JsonResult userRoleList(Map paramsMap) {
    String userId = StringUtils.getMapKeyValue(paramsMap, "userId");
    String userOrgId = StringUtils.getMapKeyValue(paramsMap, "orgId");
    if (StringUtils.isBlank(userId)) {
      return JsonResult.putFail(JsonConstans.ERR_WRONG_PARAM);
    }
    String sql = "SELECT role.id,role.cnName,role.`code`\n" + " FROM sys_role role ";
    String orgId = SystemSession.getOrgId();
    if (StringUtils.isBlank(orgId)) {
      return JsonResult.putSuccess();
    }
    Map<String, Object> conditionParams = new HashMap<>(2);
    sql += " WHERE role.orgId =:orgId";
    if (!SysConstants.ROOT_ID.getValue().equals(orgId)) {
      conditionParams.put("orgId", orgId);
    } else {
      conditionParams.put("orgId", userOrgId);
    }
    Map<String, Object> dataMap =
        sysUserRepository.findPageByNativeQueryFileds(
            sql, conditionParams, Transformers.aliasToBean(SysRoleEntity.class), null, null);
    if (dataMap != null) {
      List<SysRoleUserEntity> sysRoleUserEntities =
          sysUserRepository.findByFiled(SysRoleUserEntity.class, "userId", userId);
      List<SysRoleEntity> sysRoleEntityList =
          (List<SysRoleEntity>) dataMap.get(SysConstants.ROWS.getValue());
      for (SysRoleEntity roleEntity : sysRoleEntityList) {
        roleEntity.setIsCheck(Boolean.FALSE);
        for (SysRoleUserEntity sysRoleUserEntity : sysRoleUserEntities) {
          if (roleEntity.getId().equals(sysRoleUserEntity.getRoleId())) {
            roleEntity.setIsCheck(Boolean.TRUE);
            break;
          }
        }
      }
      return JsonResult.putSuccess(sysRoleEntityList);
    }
    return null;
  }

  @Override
  public List<SysRoleEntity> userRoleList(String uId) {

    return null;
  }

  @Override
  public void updUserParamByLoginSuccess(HttpServletRequest httpServletRequest)
      throws UnknownHostException {
    sysUserRepository.updUserParamByLoginSuccess(httpServletRequest);
  }

  @Override
  public JsonResult activeCode(String code) {
    LinkedHashMap linkedHashMap = new LinkedHashMap<String, Object>();
    linkedHashMap.put("id", code);
    linkedHashMap.put("enabled", true);
    if (sysUserRepository.updateFileds(linkedHashMap) > 0) {
      return JsonResult.putSuccess();
    }
    return JsonResult.putFail();
  }

  //  @Override
  //  public void updUserParamByLoginOut(HttpServletRequest httpServletRequest)
  //      throws UnknownHostException {
  //    loginSuccessOutParamSet(false, httpServletRequest);
  //  }

  //  private void loginSuccessOutParamSet(
  //      boolean loginSuccessOut, HttpServletRequest httpServletRequest) throws
  // UnknownHostException {
  //    LinkedHashMap<String, Object> paramMap = new LinkedHashMap();
  //    SysUserEntity user = SysUserUtils.getCurrentSysUser();
  //    Timestamp nowTime = new Timestamp(System.currentTimeMillis());
  //    paramMap.put("loginTime", nowTime.toString());
  //    if (loginSuccessOut) {
  //      paramMap.put("updateTime", nowTime.toString());
  //    } else {
  //      paramMap.put("loginOutTime", nowTime.toString());
  //    }
  //    paramMap.put("updateId", SysUserUtils.getCurrentSysUser().getId());
  //    paramMap.put("loginIp", IpUtil.getIpAddrByNginx(httpServletRequest));
  //    paramMap.put("id", user.getId());
  //    sysUserRepository.updateFileds(paramMap);
  //  }

  /**
   * 如果jwtToken存在且不过期这里不应该执行查询账号操作而是根据token生成账户，修改账户操作就必须查询最新数据
   *
   * @param s username
   * @return
   * @throws UsernameNotFoundException
   */
  @Transactional(readOnly = true)
  @Override
  public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    String[] usernameJwtToken = s.split(",");
    Map<String, Object> jwtTokenMap = null;
    if (usernameJwtToken.length > 1) {
      try {
        jwtTokenMap = jwtUtil.validateToken(usernameJwtToken[0]);
      } catch (Exception e) {
        return sysUserRepository.getSysUserEntityByCode(usernameJwtToken[1]).createSystemUserDto();
      }
      if (jwtTokenMap != null) {
        return UserDetailsImpl.createUserDetailByMap(jwtTokenMap);
      }
    }
    return sysUserRepository.getSysUserEntityByCode(s).createSystemUserDto();
  }

  @Override
  public List<SysUserEntity> findData(Object o) {
    return null;
  }

  //  private SysUserEntity getSysUserEntityByCode(String username) {
  //    /** 查询用户根据code=username */
  //    SysUserEntity user = getUserMapByCode(username);
  //    if (user == null) {
  //      return null;
  //    }
  //    // 查询用户权限,多个权限能同级但不能上下级
  //    Map paramMap = new HashMap();
  //    paramMap.put("userId", user.getId());
  //    String sql = "SELECT ru.* from sys_role_user ru where ru.userId=:userId";
  //    List<SysRoleUserEntity> resRoleUser = sysUserRepository.findByNativeQuery(sql, paramMap,
  // Transformers.aliasToBean(SysRoleUserEntity.class));
  //    if (resRoleUser != null && resRoleUser.size() > 0) {
  //      paramMap.clear();
  //      List<String> paramList = new ArrayList();
  //      for (SysRoleUserEntity roleUser : resRoleUser) {
  //        paramList.add(roleUser.getRoleId());
  //      }
  //      paramMap.put("roleIdList", paramList);
  //      sql = "SELECT r.id,r.name from sys_role r where r.id in (:roleIdList)";
  //      List<SysRoleEntity> resRoleList =
  //              sysUserRepository.findByNativeQuery(sql, paramMap,
  // Transformers.aliasToBean(SysRoleEntity.class));
  //      //      查询该用户所有权限所有菜单
  //      if (resRoleList != null && resRoleList.size() > 0) {
  //        user.setRoles(resRoleList);
  //        sql = "SELECT * from sys_role_menu where roleId in(:roleIdList)";
  //        //                用户多个权限下权限不为上下级关系只能同级,或不同级等级差，
  //        // 只需要拿到最高级别权限的权限菜单中间表记录，如果最高级别权限有多个，则需要同时都获取到
  //        List<SysRoleMenuEntity> roleMenuList =
  //                sysUserRepository.findByNativeQuery(sql, paramMap,
  // Transformers.aliasToBean(SysRoleMenuEntity.class));
  //        if (roleMenuList != null && roleMenuList.size() > 0) {
  //          sql = "SELECT * from sys_menu where id in(:menuIdList)";
  //          paramMap.clear();
  //          paramList.clear();
  //          for (SysRoleMenuEntity roleMenu : roleMenuList) {
  //            paramList.add(roleMenu.getMenuId());
  //          }
  //          paramMap.put("menuIdList", paramList);
  //          List<SysMenuEntity> resMenuList =
  //                  sysUserRepository.findByNativeQuery(sql, paramMap,
  // Transformers.aliasToBean(SysMenuEntity.class));
  //          if (resMenuList != null && resMenuList.size() > 0) {
  //            //            将菜单menu归类到对应用户权限下
  //            resMenuList:
  //            for (SysMenuEntity menuEntity : resMenuList) {
  //              for (SysRoleMenuEntity sysRoleMenuEntity : roleMenuList) {
  //                if (menuEntity.getId().equals(sysRoleMenuEntity.getMenuId())) {
  //                  for (SysRoleEntity roleEntity : resRoleList) {
  //                    if (roleEntity.getId().equals(sysRoleMenuEntity.getRoleId())) {
  //                      HashSet<SysMenuEntity> menuSet = roleEntity.getMenus();
  //                      if (menuSet == null) {
  //                        menuSet = new HashSet<SysMenuEntity>();
  //                        roleEntity.setMenus(menuSet);
  //                      }
  //                      menuSet.add(menuEntity);
  //                      continue resMenuList;
  //                    }
  //                  }
  //                }
  //              }
  //            }
  //            // 将菜单menu累计上下级
  //
  //            //            登陆菜单
  //            user.setMenus(SysMenuEntity.upDownMenu(resMenuList));
  //          }
  //          //    需要更新登录成功后的参数信息无法传request获取ip，
  //          // 在sysUserRepository.update()无法获取当前线程的登陆者对象SysUserEntity u =
  //          // SysUserUtils.getCurrentSysUser();还没set进去，
  //          // system.currentTimeMillis()));
  //          //    在AuthenticationSuccessHandlerImpl登录成功处理类可以解决这些问题
  //          //    sysUserRepository.update(user);
  //        }
  //      }
  //    }
  //    return user;
  //  }
}
